#include "plotshowwidget.h"
#include "plotcurveviewitem.h"
#include "datacollector.h"
#include <QListWidget>
#include <ctime>

PlotShowWidget::PlotShowWidget(QWidget *parent) :
    QWidget(parent)
{
	for (int i = 0; i < MaxPlotViewCount; i ++)
	{
		m_plotDataArr[i] = new PlotData();
		m_plotViewArr[i] = new PlotView(m_plotDataArr[i]);
	}

	// note: place for config.xml
	// plotview adjust
	// stat plot view scale 0~100
	m_plotViewArr[3]->AddCurve("cpu_ratio");
	m_plotViewArr[3]->AddCurve("page_in");
	m_plotViewArr[3]->AddCurve("page_out");
	m_plotViewArr[3]->AddCurve("intr");
	m_plotViewArr[3]->AddCurve("context_switch");
	m_plotViewArr[3]->AddCurve("packet_in");
	m_plotViewArr[3]->AddCurve("packet_out");
	m_plotViewArr[3]->setAxisScale(0, 0, 100);
	m_plotViewArr[3]->addLegend("Resource");
	m_plotViewArr[3]->setAxisXTitle("time/s");
	m_plotViewArr[3]->setAxisYTitle("ratio/%");

	// add curves for tps plot
	m_plotViewArr[2]->AddCurve("ContractCreate");
	m_plotViewArr[2]->AddCurve("ContractModify");
	m_plotViewArr[2]->AddCurve("ContractDelete");
	m_plotViewArr[2]->AddCurve("TradePayment");
	m_plotViewArr[2]->AddCurve("TradeCharge");
	m_plotViewArr[2]->AddCurve("TradeLookup");
	m_plotViewArr[2]->AddCurve("UserBalanceLookup");
	m_plotViewArr[2]->AddCurve("UserContractLookup");
	m_plotViewArr[2]->AddCurve("Rejection");
	m_plotViewArr[2]->AddCurve("TriggerTps");
	m_plotViewArr[2]->AddCurve("Error");
	m_plotViewArr[2]->AddCurve("Tps");
	m_plotViewArr[2]->addLegend("TPS");
	m_plotViewArr[2]->setAxisXTitle("time/s");
	m_plotViewArr[2]->setAxisYTitle("tps");

	// add curves for resp plot
	m_plotViewArr[1]->AddCurve("Resp");
	m_plotViewArr[1]->addLegend("TRT");
	m_plotViewArr[1]->setAxisXTitle("time/s");
	m_plotViewArr[1]->setAxisYTitle("trt/s");
	m_plotViewArr[1]->setAxisScale(0, 0, 10);

	// add curves for user plot
	m_plotViewArr[0]->AddCurve("User");
	m_plotViewArr[0]->addLegend("USER");
	m_plotViewArr[0]->setAxisXTitle("time/s");
	m_plotViewArr[0]->setAxisYTitle("user");

	for (int i = 0; i < MaxPlotViewCount; i ++){
		m_curveShowArr[i] = new CurveShowWidget(m_plotDataArr[i]);
		m_plotViewArr[i]->setCurveShowWidget(m_curveShowArr[i]);
		QObject::connect(m_plotViewArr[i], SIGNAL(zoomStateChanged(bool)), this, SLOT(ZoomHandle(bool)));
		QObject::connect(m_curveShowArr[i], SIGNAL(checkStateChanged(std::string, bool)), m_plotViewArr[i], SLOT(SetCurveState(std::string, bool)));
		QObject::connect(m_curveShowArr[i], SIGNAL(selectionChanged(std::string)), m_plotViewArr[i], SLOT(BoldCurve(std::string)));
	}

    this->setupUI();

	DataCollector *collector = DataCollector::GetInstance();
	QObject::connect(collector, SIGNAL(sumTranDataArrived(QList<TTranData>)), this, SLOT(SumTranDataHandle(QList<TTranData>)));
	QObject::connect(collector, SIGNAL(sumUserDataArrived(int)), this, SLOT(SumUserDataHandle(int)));
	QObject::connect(collector, SIGNAL(rstatDataArrived(TRstatData)), this, SLOT(RstatDataHandle(TRstatData)));
}

void PlotShowWidget::setupUI()
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);

	gridLayout = new QGridLayout();
	gridLayout->addWidget(m_plotViewArr[0], 0, 0);
	gridLayout->addWidget(m_plotViewArr[1], 0, 1);
	gridLayout->addWidget(m_plotViewArr[2], 1, 0);
	gridLayout->addWidget(m_plotViewArr[3], 1, 1);

	mainLayout->addLayout(gridLayout);
    QFrame *line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    mainLayout->addWidget(line);

	// add plot curve view
	hLayout = new QHBoxLayout();

	mainLayout->addLayout(hLayout);
}

// slots
void PlotShowWidget::ZoomHandle(bool zoom)
{
	PlotView *view = (PlotView *)(this->sender());
	if(zoom){ // zoom in
		view->setWidth(view->getWidth() * 2);
		view->setHeight(view->getHeight() * 3 / 2);
		for (int i = 0; i < MaxPlotViewCount; i ++)
		{
			gridLayout->removeWidget(m_plotViewArr[i]);
			m_plotViewArr[i]->hide();
		}
		
		view->show();
		gridLayout->addWidget(view, 0, 0, 2, 2);

		hLayout->addWidget(view->getCurveShowWidget());
		view->getCurveShowWidget()->show();
	} else { // zoom out
		view->setWidth(view->getWidth() / 2);
		view->setHeight(view->getHeight() * 2 / 3);
		gridLayout->removeWidget(view);
		view->hide();
		for (int i = 0; i < MaxPlotViewCount; i ++)
		{
			gridLayout->addWidget(m_plotViewArr[i]);
			m_plotViewArr[i]->show();
		}
		hLayout->removeWidget(view->getCurveShowWidget());
		view->getCurveShowWidget()->hide();
	}
}

void PlotShowWidget::SumTranDataHandle(QList<TTranData> incTranData)
{
	static double tps_xdata[MaxCurveCount], tps_ydata[MaxCurveCount];
	static double resp_ydata[MaxCurveCount];

	int time_now = time(NULL);
	for(int i = 0; i < incTranData.count(); i ++){
		tps_xdata[i] = (double)(time_now);
		tps_ydata[i] = incTranData[i].tps;
		resp_ydata[i] = incTranData[i].resp;
		// the average resp time
		if(tps_ydata[i] != 0) resp_ydata[i] /= tps_ydata[i];
	}

	// resp plot view
	m_plotViewArr[1]->AddData(tps_xdata[11], resp_ydata[11], 0); // the 11 need to be replaced with some meaningful var
	CurveShowWidget *widget = (CurveShowWidget *)m_plotViewArr[1]->getCurveShowWidget();
	widget->SetLastValue(resp_ydata);
	// tps plot view
	widget = (CurveShowWidget *)m_plotViewArr[2]->getCurveShowWidget();
	widget->SetLastValue(tps_ydata);
	m_plotViewArr[2]->AddData(tps_xdata, tps_ydata);
}

void PlotShowWidget::SumUserDataHandle(int user)
{
	// user plot view, only one curve
	CurveShowWidget *widget = (CurveShowWidget *)m_plotViewArr[0]->getCurveShowWidget();
	widget->SetLastValue(0, (double)user);
	m_plotViewArr[0]->AddData((double)time(NULL), (double)user, 0);
}

void PlotShowWidget::RstatDataHandle(TRstatData rstatData)
{
	static const int RstatFields = 7;
	static double rstat_xdata[RstatFields], rstat_ydata[RstatFields];

	int time_now = time(NULL);
	for(int i = 0; i < RstatFields; i ++) rstat_xdata[i] = (double)time_now;

	rstat_ydata[0] = rstatData.cpu_ratio;
	rstat_ydata[1] = rstatData.page_in;
	rstat_ydata[2] = rstatData.page_out;
	rstat_ydata[3] = rstatData.intr;
	rstat_ydata[4] = rstatData.context_sw;
	rstat_ydata[5] = rstatData.packet_in;
	rstat_ydata[6] = rstatData.packet_out;

	CurveShowWidget *widget = (CurveShowWidget *)m_plotViewArr[3]->getCurveShowWidget();
	widget->SetLastValue(rstat_ydata);
	m_plotViewArr[3]->AddData(rstat_xdata, rstat_ydata);
}
